module Orator

  # This is used as a context for the client execution.
  class MiddleGround

    # Provides access to the client.
    #
    # @return [Client]
    attr_reader :client

    # Provides access to the list of clients that are connected.
    #
    # @return [Set<Client>]
    attr_reader :clients

    # Initialize the class.
    def initialize(client, clients)
      @client  = client
      @clients = clients
      @struct  = ::Orator::OpenStruct.new
    end

    # This sends a message to the client.
    #
    # @param data [Hash] the data to be sent to the client.
    # @return [void]
    def send(data)
      @client.socket.send Oj.dump(data, :mode => :compat)
    end

    # This builds a message from a hash and an event.
    #
    # @param event [String, Symbol] the event for the message.
    # @param data [Hash] the data for the message.
    #
    # @return [Hash]
    def message(event, data)
      new_data = { "event" => event.to_s }

      data.each do |k, v|
        new_data[k.to_s] = v
      end

      new_data
    end

    # This delegates the rest of the requests to the struct.
    def method_missing(method, *args, &block)
      super unless respond_to_missing?(method)

      @struct.public_send(method, *args, &block)
    end

    # Lets ruby know we're doing some {#method_missing} magic.
    def respond_to_missing?(method, include_private = false)
      @struct.respond_to?(method, include_private)
    end
  end
end
